using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Data;
using System.Configuration;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using CookComputing.XmlRpc;
using ITCrossing.Common;
using ITCrossing.Threading;
using DotNetNuke.Entities.Portals;

// Adapted from SubText Notification.cs
namespace ITCrossing.Tracking
{
	public class TrackingService
	{
		/// <summary>
		/// Posts trackbacks and pingbacks for the specified entry.
		/// </summary>
		/// <param name="trackOrPings"></param>
		/// <param name="title"></param>
		/// <param name="postUrl"></param>
		/// <param name="blogName"></param>
		/// <param name="summary"></param>
		/// <param name="postText"></param>
		/// <param name="autoProcessTrackbacksOrPings"></param>
		public static void TrackbackOrPing(string[] trackOrPings, string title,
			string postUrl, string blogName, string summary, string postText,
			bool autoProcessTrackbacksOrPings, PortalSettings portalSettings)
		{
			if (trackOrPings != null && trackOrPings.Length > 0 && !string.IsNullOrEmpty(postUrl))
			{
				TrackbackOrPingNotifier notify = new TrackbackOrPingNotifier();
				notify.PostUrl = postUrl;
				notify.BlogName = blogName;
				notify.Title = title;
				notify.Description = summary;
				notify.Text = postText;
				notify.Trackbacks = trackOrPings;
				notify.AutoProcessTrackbacksOrPings = autoProcessTrackbacksOrPings;
				notify.PortalSettings = portalSettings;

				//This could take a while, do it on another thread
				ManagedThreadPool.QueueUserWorkItem(notify.SendTrackBacksOrPings);
			}
		}


		

		/// <summary>
		/// Clas used to send Trackback or Ping notification
		/// </summary>
		private class TrackbackOrPingNotifier
		{
			public string[] Trackbacks;
			public string Title;
			public string PostUrl;
			public string BlogName;
			public string Description;
			public string Text;
			public bool AutoProcessTrackbacksOrPings;
			public PortalSettings PortalSettings;

			/// <summary>
			/// Notifies the specified state.
			/// </summary>
			/// <param name="state">The state.</param>
			public void SendTrackBacksOrPings(object state)
			{
				try
				{
					SendTrackBacksOrPings();
				}
				catch (XmlRpcFaultException)
				{
					throw;
				}
				catch (Exception e)
				{
					DotNetNuke.Services.Exceptions.Exceptions.LogException(e);
				}
			}
			public void SendTrackBacksOrPings()
			{

				Uri postUri = HtmlHelper.ParseUri(PostUrl);
				if (postUri == null) return;

				// Add Trackbacks and Pings to a list we can add to if we need to autoprocess 
				// links in the page.
				List<Uri> trackbackList = new List<Uri>();

				// Try to load the Trackbacks as Uris
				foreach (string trackbackUrl in Trackbacks)
				{
					if (string.IsNullOrEmpty(trackbackUrl)) continue;
					Uri trackback = HtmlHelper.ParseUri(trackbackUrl);
					if (trackback == null)
					{
						throw new XmlRpcFaultException(0,MetaPostServices.GetStringGlobal("InvalidTrackbackUrl","One of the Trackback URLs seems to be invalid.  Please check each URL you entered.", PortalSettings.DefaultLanguage));
					}
					trackbackList.Add(trackback);
				}

				List<TrackingStructs.PingBack> pingbackList = new List<TrackingStructs.PingBack>();

				// Auto process Trackbacks and Pings if Needed
				if (AutoProcessTrackbacksOrPings)
				{
					
					//Get the links from the last post
					StringCollection links = HtmlHelper.GetLinks(Text);
					

					//Do we have links
					if (links != null && links.Count > 0)
					{
						foreach (string link in links)
						{
							// make sure we're not including a link to IT Crossing
							if (link == "http://www.itcrossing.com/") continue;

							//get the page text
							Uri targetUri = HtmlHelper.ParseUri(link);
							if (targetUri == null)
								continue;

							string pageText = HttpHelper.GetPageText(targetUri);

							// Now that we have the page text, try to get a ping URL.
							string pingServerUrl = GetPingBackURL(pageText, postUri);
							if (!string.IsNullOrEmpty(pingServerUrl))
							{
								// PINGBACK
								// Check the pingServerUri
								Uri pingServerUri = HtmlHelper.ParseUri(pingServerUrl);
								if (pingServerUri == null) continue;

								TrackingStructs.PingBack pingback = new TrackingStructs.PingBack();
								pingback.SourceUri = postUri;
								pingback.TargetUri = targetUri;
								pingback.PingbackServerUri = pingServerUri;

								pingbackList.Add(pingback);
							}
							else
							{
								// TRACKBACK
								// If no ping URL, then we try to get a regular old,
								// plain-jane Trackback.
								string trackBackUrl = GetTrackBackText(pageText, targetUri, postUri);
								Uri trackBackUri = HtmlHelper.ParseUri(trackBackUrl);
								if (trackBackUri != null && !trackbackList.Contains(trackBackUri))
									trackbackList.Add(trackBackUri); 
							}
						}
					}
				}

				// First, handle all the pings.
				if (pingbackList.Count > 0)
				{
					using (PingBackNotificatinProxy pbnp = new PingBackNotificatinProxy())
					{
						foreach (TrackingStructs.PingBack ping in pingbackList)
						{
							// This returns a bool which we could use to log success or failure
							// but for now, we just keep moving.
							bool success = pbnp.Ping(ping.SourceUri, ping.TargetUri, ping.PingbackServerUri);
							bool test = success;
						}
					}
				}
				// Next, handle all the trackbacks.
				if (trackbackList.Count > 0)
				{
					TrackBackNotificationProxy tbnp = new TrackBackNotificationProxy();
					foreach (Uri trackback in trackbackList)
					{
						// This returns a bool which we could use to log success or failure
						// but for now, we just keep moving.
						bool success = (!tbnp.TrackBackPing(trackback, Title, postUri, BlogName, Description));
					}
				}

				// As Napoleon Dynamite's brother Kip would say, "Yesss!"
				return;
			}

			// Originally appeared in the SubText PingBackNotificationProxy, but moved here.
			private string GetPingBackURL(string pageText, Uri postUrl)
			{
				if (!Regex.IsMatch(pageText, postUrl.ToString(), RegexOptions.IgnoreCase | RegexOptions.Singleline))
				{
					if (pageText != null)
					{
						string pat = "<link rel=\"pingback\" href=\"([^\"]+)\" ?/?>";
						Regex reg = new Regex(pat, RegexOptions.IgnoreCase | RegexOptions.Singleline);
						Match m = reg.Match(pageText);
						if (m.Success)
						{
							return m.Result("$1");
						}
					}
				}
				return null;
			}

			// Originally appeared in the SubText TrackBackNotificationProxy, but moved here.
			private string GetTrackBackText(string pageText, Uri url, Uri postUrl)
			{
				//if (!Regex.IsMatch(pageText, postUrl.ToString(), RegexOptions.IgnoreCase | RegexOptions.Singleline))
				//{
					string sPattern = @"<rdf:\w+\s[^>]*?>(</rdf:rdf>)?";
					Regex r = new Regex(sPattern, RegexOptions.IgnoreCase);
					Match m;

					for (m = r.Match(pageText); m.Success; m = m.NextMatch())
					{
						if (m.Groups.ToString().Length > 0)
						{
							string text = m.Groups[0].ToString();
							//if (text.IndexOf(url.ToString()) > 0)
							//{
								string tbPattern = "trackback:ping=\"([^\"]+)\"";
								Regex reg = new Regex(tbPattern, RegexOptions.IgnoreCase);
								Match m2 = reg.Match(text);
								if (m2.Success)
								{
									return m2.Result("$1");
								}
								return text;
							//}
						}
					}
				//}
				return null;
			}
		}
	}
}
